//
//  MyDocument.m
//  AKAnimationUtility
//
//  Created by Ben Chen on 3/2/08.
//  Copyright Sleeper 2008 . All rights reserved.
//

#import <QuartzCore/CoreAnimation.h>

#import "MyDocument.h"

@implementation MyDocument

#pragma mark Run animation

- (CGImageRef)imageRefWithName:(NSString*)fileName type:(NSString*)type {
	
	CGImageRef retVal;
	
	CGImageSourceRef source;
	source = CGImageSourceCreateWithURL((CFURLRef)[NSURL fileURLWithPath:
												   [[NSBundle mainBundle] pathForResource:fileName ofType:type]], NULL);
	retVal = CGImageSourceCreateImageAtIndex(source, 0, NULL);
	CFRelease(source);
	
	return retVal;
}	

- (CAAnimationGroup*)animationGroup {
	
	// get the KVC model of the managed object
	id managedObject = [_dataController content];
	
	NSMutableArray	*array = [NSMutableArray array];
	
	CGFloat totalDuration = [[managedObject valueForKey:@"duration"] floatValue];
	
	NSSet *keyFrameCurves	= [managedObject valueForKey:@"keyFrameCurves"];	
	if ([keyFrameCurves count] > 0 ) {
		// Key frame animation for position
		CGMutablePathRef thePath = CGPathCreateMutable();
		
		CGPathMoveToPoint(thePath,NULL,[[managedObject valueForKey:@"sX"] floatValue],[[managedObject valueForKey:@"sY"] floatValue]);
		
		NSArray *unsortedData	= [keyFrameCurves allObjects];
		NSArray *sortedData		= [unsortedData sortedArrayUsingDescriptors:[self sortDescriptorForCurves]];
		for (id curve in sortedData) {
			CGPathAddCurveToPoint(thePath, NULL, [[curve valueForKey:@"cx1"] floatValue], [[curve valueForKey:@"cy1"] floatValue], [[curve valueForKey:@"cx2"] floatValue], [[curve valueForKey:@"cy2"] floatValue], [[curve valueForKey:@"x"] floatValue], [[curve valueForKey:@"y"] floatValue]);
		}
		
		CAKeyframeAnimation * theAnimation;
		
		theAnimation			= [CAKeyframeAnimation animationWithKeyPath:@"position"];
		theAnimation.path		= thePath;
		theAnimation.duration	= totalDuration;
		
		[array addObject:theAnimation];
		CFRelease(thePath);	
	} else {
		// Basic animation for position
		CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
		animation.fromValue	= [NSValue valueWithPoint:NSMakePoint([[managedObject valueForKey:@"sX"] floatValue], [[managedObject valueForKey:@"sY"] floatValue])];
		animation.toValue	= [NSValue valueWithPoint:NSMakePoint([[managedObject valueForKey:@"eX"] floatValue], [[managedObject valueForKey:@"eY"] floatValue])];
		animation.duration	= totalDuration;
		[array addObject:animation];
	}
	
	// Basic animations for size change
	NSSet *sizes = [managedObject valueForKey:@"sizes"];
	if ([sizes count] > 0) {
		NSArray *unsortedData	= [sizes allObjects];
		NSArray *sortedData		= [unsortedData sortedArrayUsingDescriptors:[self sortDescriptorForCurves]];
		
		CGFloat beginTime = 0.0;
		for (id aSize in sortedData) {
			CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"bounds.size"];
			animation.fromValue = [NSValue valueWithSize:NSMakeSize([[aSize valueForKey:@"sW"] floatValue], [[aSize valueForKey:@"sH"] floatValue])];
			animation.toValue	= [NSValue valueWithSize:NSMakeSize([[aSize valueForKey:@"eW"] floatValue], [[aSize valueForKey:@"eW"] floatValue])];
			animation.beginTime	= beginTime;
			animation.duration	= totalDuration * [[aSize valueForKey:@"timePercent"] floatValue];
			beginTime			+= animation.duration;
			[array addObject:animation];
		}
	}
	
	CAAnimationGroup *group = [[CAAnimationGroup alloc] init];
	group.animations	= [array copy];
	group.duration		= totalDuration;
	group.autoreverses	= [[managedObject valueForKey:@"autoreverses"] boolValue];
	
	if ([[managedObject valueForKey:@"repeatForever"] boolValue])
		group.repeatCount	= 1e100f;
	else
		group.repeatCount	= 1;
	
	group.timingFunction= [CAMediaTimingFunction functionWithControlPoints:[[managedObject valueForKey:@"timeX1"] floatValue] :[[managedObject valueForKey:@"timeY1"] floatValue] :[[managedObject valueForKey:@"timeX2"] floatValue] :[[managedObject valueForKey:@"timeY2"] floatValue]];
	
	return [group autorelease];
}

- (IBAction)run:(id)sender {
	
	[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];	// disable animation actions
	
	[self stop:nil];
	
	[pieceLayer addAnimation:[self animationGroup] forKey:@"animationGroup"];
}

- (IBAction)stop:(id)sender {
	
	if ([pieceLayer animationForKey:@"animationGroup"] != nil)
		[pieceLayer removeAnimationForKey:@"animationGroup"];
}

#pragma mark Initialization

- (id)init 
{
    self = [super init];
    if (self != nil) {
		_curvesSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"creationTime" 
															ascending:YES
															 selector:@selector(compare:)];
    }
    return self;
}

- (void) dealloc {
	
	[_curvesSortDescriptor release];
	[super dealloc];
}

#pragma mark Data related

- (NSString *)windowNibName {
    return @"MyDocument";
}

- (NSArray*)sortDescriptorForCurves {
	return [NSArray arrayWithObject:_curvesSortDescriptor];
}

- (void)windowControllerDidLoadNib:(NSWindowController *)windowController {
	
    [super windowControllerDidLoadNib:windowController];
	
	// Add a new data if there isn't any
	if ([_dataController content] == nil)
		[_dataController add:nil];
	
	// Setup view
	containerLayer	= [CALayer layer];
	pieceLayer		= [CALayer layer];
	pieceLayer.contents	= (id)[self imageRefWithName:@"AK_Tiger_B_0" type:@"png"];
	pieceLayer.frame	= CGRectMake(50, 50, 200, 200);
	[containerLayer addSublayer:pieceLayer];
	
	[_renderView setLayer:containerLayer];
	[_renderView setWantsLayer:YES];
}

@end
